package com.develop.data.loan.manager.change.amount;

import com.develop.data.loan.manager.change.amount.api.LoanInstallmentAmountBudget;
import com.develop.data.loan.model.LoanContract;
import com.develop.data.loan.model.LoanInstallment;
import com.develop.data.loan.option.LoanRateType;
import org.javamoney.moneta.Money;
import org.springframework.stereotype.Component;

import javax.money.Monetary;
import javax.money.MonetaryAmount;
import javax.money.MonetaryRounding;
import javax.money.RoundingQueryBuilder;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Component("L0001B0001LoanInstallmentPrincipalBudget")
public class L0001B0001LoanInstallmentPrincipalBudget implements LoanInstallmentAmountBudget {

    /* 已发生形态转移 */
    /* 持有时间，左受制于动帐时间，右受制于转非应计时间（不计息） */
    /* LoanInstallmentPrincipalCleared对应Installment的PrincipalCleared金额字段 */
    /* 第M期为当前期，预览第N期 */

    public MonetaryAmount preview(LoanInstallment loanInstallment, LocalDateTime localDate){


        MonetaryAmount amount = Money.zero(Monetary.getCurrency("CNY"));
        LocalDateTime headDate = loanInstallment.getInstallmentHead();
        LocalDateTime tailDate = loanInstallment.getInstallmentTail();

        /* 未来期次，每期首尾左闭右开，每期天数算头不算尾 */
        if (Duration.between(localDate, headDate).toDays() > 0) {
            return Money.zero(Monetary.getCurrency("CNY"));
        }

        /* 历史期次、当前期次 */
        return loanInstallment.getInstallmentPrincipalDueAccrual().subtract(loanInstallment.getInstallmentPrincipalOverdueCleared());
    }

    public MonetaryAmount execute(LoanInstallment loanInstallment, LocalDateTime localDate, MonetaryAmount amount){

        /* 有借必有贷 */
        /* 还款金额任意，按金额依次扣除，直到扣完 */
        /* 第M期为当前期，动帐第N期 */

        LoanContract contract = loanInstallment.getLoanContract();
        List<LoanInstallment> loanInstallments = contract.getLoanInstallments();
        LoanRateType rateType = contract.getLoanRateType();
        BigDecimal rateDaily = new BigDecimal(contract.getContractRateValue());
        MonetaryRounding rounding = Monetary.getRounding(RoundingQueryBuilder.of().setScale(2).set(RoundingMode.FLOOR).build());

        LocalDateTime cursorDate = loanInstallment.getInstallmentCursor();
        LocalDateTime freezeDate = Optional.ofNullable(loanInstallment.getInstantFrozen()).orElse(LocalDateTime.MAX);

        LocalDateTime valueDate = contract.getContractValueDate();
        LocalDateTime headDate = loanInstallment.getInstallmentHead();
        LocalDateTime tailDate = loanInstallment.getInstallmentTail();


        LocalDateTime leftDate;
        LocalDateTime rightDate;

        MonetaryAmount amountPreviewed = this.preview(loanInstallment, localDate);

        if(amount.isGreaterThanOrEqualTo(amountPreviewed)){

            loanInstallment.setInstallmentPrincipalDueAccrual(loanInstallment.getInstallmentPrincipalDueAccrual().subtract(amountPreviewed));
            loanInstallment.setInstallmentPrincipalCleared(loanInstallment.getInstallmentPrincipalCleared().add(amountPreviewed));
            /* 当前期次，到期应还利息也随本金变化而变化 */
            /* 历史期次，到期应该本金减少，到期应还利息增速减缓 */
            /* 未来期次，到期应该本金不动，到期应还利息不动 */
            if(Duration.between(headDate, localDate).toDays() >= 0 && Duration.between(localDate, tailDate).toDays() >= 0){
                /* 第M期为当前期，动帐第N期，M=N时 */
                long days = Duration.between(localDate, loanInstallment.getInstallmentTail()).toDays() - 1; /* 剩余日期，动帐日期到期尾，左开右开 */
                loanInstallment.setInstallmentInterestDueAccrual(
                    loanInstallment.getContractPrincipalAccrualOpening().subtract(
                            loanInstallment.getInstallmentPrincipalCleared()
                    ).multiply(days).multiply(rateDaily).with(rounding)
                );
            }

            /* 动帐日期 */
            loanInstallment.setInstallmentCursor(localDate);
            return amount.subtract(amountPreviewed);
        }

        loanInstallment.setInstallmentPrincipalDueAccrual(loanInstallment.getInstallmentPrincipalDueAccrual().subtract(amount));
        loanInstallment.setInstallmentPrincipalCleared(loanInstallment.getInstallmentPrincipalCleared().add(amount));
        /* 当期期次，到期应还利息也随本金变化而变化 */
        /* 历史期次，到期应该本金减少，到期应还利息增速减缓 */
        /* 未来期次，到期应该本金不动，到期应还利息不动 */
        if( Duration.between(headDate, localDate).toDays() >= 0 && Duration.between(localDate, tailDate).toDays() >= 0 ){
            /* 第M期为当前期，动帐第N期，M=N时 */
            long days = Duration.between(localDate, loanInstallment.getInstallmentTail()).toDays() - 1; /* 剩余日期，动帐日期到期尾，左开右开 */
            loanInstallment.setInstallmentInterestDueAccrual(
                loanInstallment.getContractPrincipalAccrualOpening().subtract(
                        loanInstallment.getInstallmentPrincipalCleared()
                ).multiply(days).multiply(rateDaily).with(rounding)
            );
        }
        /* 动帐日期 */
        loanInstallment.setInstallmentCursor(localDate);
        return Money.zero(Monetary.getCurrency("CNY"));

    }

}
